#include "CurtainActManager.h"
#include <dirent.h>
#include "Util/logc.h"
#include "mediaPriv.h"
#include "ConfigApi.h"
#include "ScreenMirrorStream.h"
#include "PictureFileStream.h"
#include "VideoFileStream.h"
#include "RtspClientStream.h"
#include "Mp4ClientStream.h"
#include "UsbAVStream.h"
#include "UsbInStream.h"
#include "AudioInMgr.h"
#include "mdns.h"
#include "MediaTcpClient.h"
#include "UsbAVStream.h"
#include "StreamerCurtainPlay.h"
#include "MediaUdpServer.h"
#include "MediaUdpClient.h"
#include <iostream>  
#include <sstream> 
#include "MsgQueueManage.h"
#include "BgmListManager.h"



//#define MULTICAMERA_CUSTOMER

using namespace std;
using namespace ConfigApi;
extern int MEDIA_UacInStart(int channel);
extern int MEDIA_UacInStop(void);

extern "C" int HdmiInStatus(void);


extern "C" int getStreamInfo(int streamType, StreamInfo* pStreamInfo, int *streamNum)
{ 
    //printf("enter getStreamInfo\n");
    if(Media::CurtainActManager::instance()->getStreamInfo(streamType, pStreamInfo, streamNum))
    {
        return 0;
    }

    return -1;   
}

extern "C" int getCurtainLayout(CurtainInfo* pCurtainInfo)
{
    //printf("enter getCurtainLayout\n");
    if(Media::CurtainActManager::instance()->getCurtainLayout(pCurtainInfo))
    {
        return 0;
    }

    return -1;
}

extern "C" int getCurtainPlayState(PlayState *state)
{
    if(Media::CurtainActManager::instance()->getCurtainPlayState(state))
    {
        return 0;
    }

    return -1; 
}

extern "C" int isVideoDirectTransfer()
{
    bool isH26x = false;
    std::string usbPort;

    Media::CurtainActManager::instance()->usbVideoRealTimeInfo(usbPort, isH26x);

    if(isH26x)
    {
        return 0;
    }

    return -1;    
}

namespace Media{

CurtainActManager*       CurtainActManager::sm_curtainActMgrIns;
std::mutex 		         CurtainActManager::sm_insMutex;

CurtainActManager* CurtainActManager::instance()
{
	if(sm_curtainActMgrIns == nullptr)
    {
        std::lock_guard<std::mutex> guard(sm_insMutex);
        if(sm_curtainActMgrIns == nullptr)
        {
            sm_curtainActMgrIns = new CurtainActManager();
        }
    }
    return sm_curtainActMgrIns;
}


bool CurtainActManager::getJsonTable(const string filePath, Json::Value &table){
    std::lock_guard<std::mutex> guard(m_jsonFileMutex);
    ifstream ifs;
    Json::Reader reader;
	ifs.open(filePath); //获取当前配置文件中的所有配置
	if(!ifs.is_open()) {
		LOG_PrintError("faild to open ifstream\n");
		return false;
    }
    if (!reader.parse(ifs, table))
	{
		LOG_PrintError("faild to read json data from ifstream\n");
        ifs.close();
		return false;
	}
	ifs.close();
    return true;
}

bool CurtainActManager::setJsonTable(const string filePath, Json::Value table){
    std::lock_guard<std::mutex> guard(m_jsonFileMutex);
	ofstream ofs;
	ofs.open(filePath);
    if(!ofs.is_open()) {
		LOG_PrintError("faild to open ofstream\n");
		return false;
    }
	ofs << table.toStyledString();
	ofs.close();
    return true;
}

bool CurtainActManager::initCurtianConfig(){
    //读取默认配置和当前配置成json格式
    Json::Value defaultCurtainConfig;
    if(!getJsonTable(defaultConfigPathCurtain, defaultCurtainConfig)){
        LOG_PrintError("error to get default curtain config\n");
        return false;
    }
    Json::Value CurtainConfig;
    if(!getJsonTable(configPathCurtain, CurtainConfig)){
        LOG_PrintError("error to get  curtain config\n");
        return false;
    }
    Json::Value newCurtainConfig(Json::arrayValue);
    //获取当前主配置中的所有场景编号存储到一个set中
    set<int> curNumbers;
    Json::Value layouts = CurtainConfig["Layouts"];
	for(uint i = 0; i < layouts.size(); i++){
		if(!layouts[i].isMember("Number") || !layouts[i]["Number"].isInt()){
			LOG_PrintError("json data format invalid\n");
			return false;
		}
		int number = layouts[i]["Number"].asInt();
		curNumbers.insert(number);
        if(number == 0 ){
            //LOG_PrintWarn("set.insert(number): %d\n", number);
            newCurtainConfig.append(layouts[i]);
        }
        //LOG_PrintInfo("set.insert(number): %d\n", number);
	}
    //遍历场景列表
    Json::Value defaultLayouts = defaultCurtainConfig["Layouts"];
	for(uint i = 0; i < defaultLayouts.size(); i++){
		if(!defaultLayouts[i].isMember("Number") || !defaultLayouts[i]["Number"].isInt()){
			LOG_PrintError("json data format invalid\n");
			return false;
		}
		int number = defaultLayouts[i]["Number"].asInt();
		if(curNumbers.count(number) == 0){
            //LOG_PrintInfo("set.insert(number) not exist: %d\n", number);
            newCurtainConfig.append(defaultLayouts[i]);
        }else if(number != 0 ){
            newCurtainConfig.append(defaultLayouts[i]);
        }
	}
    //将修改好的配置配置写回文件
    CurtainConfig["Layouts"] = newCurtainConfig;
    //LOG_PrintInfo("CurtainConfig[Layouts][CurtainConfig[Layouts].size() - 1]: %s\n ", CurtainConfig["Layouts"][CurtainConfig["Layouts"].size() - 1].toStyledString().c_str());    
    setJsonTable(configPathCurtain, CurtainConfig);
    return true;
}

bool CurtainActManager::initCurtainActManager(){
    if(!initCurtianConfig()){
        return false;
    }
    return true;
}


CurtainActManager::CurtainActManager() 
{ 
    bool ret = initCurtainActManager();
    if(!ret){
        LOG_PrintError("initCurtainActManager error\n");
    }
}

CurtainActManager::~CurtainActManager() 
{ 

}

bool CurtainActManager::getSoundNode(string mark, string &iNode)
{
    char line[256] = {0};
    char member[512] ={0};
    if(access(asoundPath.c_str(), F_OK)){
            LOG_PrintError("not exist %s.\n", asoundPath.c_str());
            return false;
    }
    //通过fopen函数创建一个线程执行命令
    FILE *fp = fopen(asoundPath.c_str(), "r");
    if(!fp){
            LOG_PrintError("Fail to open %s.\n", asoundPath.c_str());
            return false;
    }
    //读取命令的返回值
    while(fgets(line, sizeof(line), fp)){
            strcat(member, line);
            if(fgets(line, sizeof(line), fp)){
                    strcat(member, line);
            }
            string card = member;
            if(card.find(mark) != card.npos){
                fclose(fp);
                int id = card[1] - 48;
                iNode = "hw:" + to_string(id) + ",0";
                return true;
            }
            memset(member, 0,sizeof(member));
    }
    fclose(fp);
    
    return false;
}

bool CurtainActManager::getFileNames(string path,vector<string>& filenames)
{
    DIR *pDir;
    struct dirent* ptr;

    if(!(pDir = opendir(path.c_str())))
    {
        mkdir(path.c_str(), 0775);
        if(!(pDir = opendir(path.c_str())))
        {
            errorf("Folder opendir:%s failed!", path.c_str());
            return false;
        }
    }
    
    while((ptr = readdir(pDir))!=0) 
    {
        if ((strcmp(ptr->d_name, ".") != 0) && (strcmp(ptr->d_name, "..") != 0))
        {
            filenames.push_back(ptr->d_name);
        }
    }
    closedir(pDir);

    return true;
}

bool CurtainActManager::typeToEnum(const std::string str, StreamInType* dst)
{
    if(str == "MIRROR")
    {
        *dst = MIRROR_STREAM;
    }
    else if(str == "BYOM")
    {
        *dst = BYOM_STREAM;
    }
    else if(str == "PICTUREFILE")
    {
        *dst = PICTUREFILE_STREAM;
    }
    else if(str == "VIDEOFILE")
    {
        *dst = VIDEOFILE_STREAM;
    }
    else if((str == "RTSP"))
    {
        *dst = RTSP_STREAM;
    }
    else if ((str == "ONLINEMP4"))
    {
        *dst = ONLINEMP4_STREAM;
    }
    else if(str == "USBTYPEAIN")
    {
        *dst = USBTYPEAIN_STREAM;
    }
    else if(str == "HDMIIN")
    {
        *dst = HDMIIN_STREAM;
    }
    else if(str == "OSD")
    {
        *dst = OSD_STREAM;
    }
    else if(str == "LINEIN")
    {
        *dst = LINEIN_STREAM;
    }
    else if(str == "MIC")
    {
        *dst = MIC_STREAM;
    }
    else if(str == "BLUETOOTH")
    {
        *dst = BLUETOOTH_STREAM;
    }
    else if(str == "USBTYPECIN")
    {
        *dst = USBTYPECIN_STREAM;
    }
    

    return true;
}
/*
bool CurtainActManager::resolutionToEnum(const std::string str, ResolutionDef* resn)
{
    if(str == "720P")
    {
        *resn = RESOLUTION_720P;
    }
    else if(str == "1080P")
    {
        *resn = RESOLUTION_1080P;
    }
    else if(str == "4K")
    {
        *resn = RESOLUTION_4K;
    }

    return true;
}*/

bool CurtainActManager::outputToEnum(const std::string str,  StreamOutInterface* type)
{
    //string 
    if(str == "RTSPMAINOUT")
    {
        *type = RTSP_MAIN_OUT;
    }
    else if(str == "RTSPSUBOUT1")
    {
        *type = RTSP_SUB_OUT1;
    }
    else if(str == "RTSPSUBOUT2")
    {
        *type = RTSP_SUB_OUT2;
    }
    else if(str == "RTSPSUBOUT3")
    {
        *type = RTSP_SUB_OUT3;
    }
    else if(str == "RTSPSUBOUT4")
    {
        *type = RTSP_SUB_OUT4;
    }    
    else if(str == "USBTYPECOUT")
    {
        *type = USBTYPEC_OUT;
    }    
    else if(str == "SDOUT")
    {
        *type = SD_OUT;
    }
    else if(str == "MIRROROUT")
    {
        *type = MIRROR_OUT;
    }
    else if(str == "USBTYPEAOUT1")
    {
        *type = USBTYPEA_OUT1;
    }
    else if(str == "USBTYPEAOUT2")
    {
        *type = USBTYPEA_OUT2;
    }
    else if(str == "HDMIOUT")
    {
        *type = HDMI_OUT;
    }
    else if(str == "LINEOUT")
    {
        *type = LINE_OUT;
    }
    else if(str == "BLUETOOTHOUT")
    {
        *type = BLUETOOTH_OUT;
    }
    else if(str == "HORNOUT")
    {
        *type = HORN_OUT;
    }
    else if(str == "BYOMOUT")
    {
        *type = BYOM_OUT;
    }
    else
    {
        errorf("StreamOutInterface not support\n"); 
        return false;
    }

    return true;
}

bool CurtainActManager::getDeviceCapacity(Json::Value &table)
{
	table["Resolution"] = "1080P";
	Json::Value tmp = Json::Value::null;
	tmp["SteramTypeDif"] = 1;
	tmp["MaxPictureNum"] = 16;
    table["caps"].append(tmp);

    tmp["SteramTypeDif"] = 2;
	tmp["MaxPictureNum"] = 8;
    table["caps"].append(tmp);

    tmp["SteramTypeDif"] = 3;
	tmp["MaxPictureNum"] = 6;
    table["caps"].append(tmp);

    tmp["SteramTypeDif"] = 4;
	tmp["MaxPictureNum"] = 4;
    table["caps"].append(tmp);
		
    return true;
}

bool CurtainActManager::getOutputInterface(Json::Value &table)
{
    Json::Value sType = Json::Value::null;
    Json::Value detail = Json::Value::null;

    sType["Type"] = "USBTYPECOUT";
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);
    
    sType.clear();
    sType["Type"] = "SDOUT";
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "BYOMOUT"; //MIRROROUT
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "HDMIOUT";
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "LINEOUT";
    sType["StreamAbility"] = AUDIO_ONLY;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "USBTYPEAOUT1";
    sType["StreamAbility"] = AUDIO_ONLY;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "USBTYPEAOUT2";
    sType["StreamAbility"] = AUDIO_ONLY;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "RTSPMAINOUT";
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);

#if 0
    sType.clear();
    sType["Type"] = "RTSPSUBOUT1";
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "RTSPSUBOUT2";
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "RTSPSUBOUT3";
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);

    sType.clear();
    sType["Type"] = "RTSPSUBOUT4";
    sType["StreamAbility"] = VIDEO_AUDIO;
    table["SupportType"].append(sType);
#endif    

    return true;
}


bool CurtainActManager::getStreamType(Json::Value &table)
{
    Json::Value sType = Json::Value::null;
    Json::Value module = Json::Value::null;
    Json::Value detail = Json::Value::null;

    /*sType.clear();
    sType["Type"] = "OSD";
    sType["StreamAbility"] = VIDEO_ONLY;
    table["SupportType"].append(sType);*/

    ///HDMI
    if(HdmiInStatus() == 1)
    {
        sType.clear();    
        sType["Type"] = "HDMIIN";
        sType["StreamAbility"] = VIDEO_AUDIO;
        table["SupportType"].append(sType);
    }

    ///PICTUREFILE
    sType.clear();
    sType["Type"] = "PICTUREFILE";
    vector<string> filenames;
    getFileNames(picturePath, filenames);
    detail.clear();
    module.clear();
    for(uint i = 0; i < filenames.size(); ++i)
    {
        detail["Content"] = filenames[i];
        detail["StreamAbility"] = VIDEO_ONLY;
        module.append(detail);
    }
    if(module.size() > 0)
    {
        sType["Modules"] = module;
        table["SupportType"].append(sType);
    }

    ///VIDEOFILE
    sType.clear();
    sType["Type"] = "VIDEOFILE";
    filenames.clear();
    getFileNames(videoPath, filenames);
    detail.clear();
    module.clear();
    for(uint i = 0; i < filenames.size(); ++i)
    {
        detail["Content"] = filenames[i];
        detail["StreamAbility"] = VIDEO_AUDIO;
        module.append(detail);
    }
    if(module.size() > 0)
    {
        sType["Modules"] = module;
        table["SupportType"].append(sType);
    }

#if 0
    getJsonTable(paramsConfigPath, configTable)        
    
	//printf("configTable =%s\n",configTable.toStyledString().c_str());

    if( (configTable.isMember("Mirror")) && (configTable["Mirror"].isMember("Protocol")) )
    {        
    	std::string value = configTable["Mirror"]["Protocol"].asString();
    	
        sType.clear();
        sType["Type"] = "MIRROR";     
        sType["StreamAbility"] = VIDEO_AUDIO; 
        sType["Content"] = value;
        table["SupportType"].append(sType);
    }
#endif

    ///USBIN
    map<string, int> abilitys;
	map<string, int>::iterator it;
	UsbAVStream::instance()->getAblilityMap(abilitys);
	sType.clear();
	module.clear();
	detail.clear();
    sType["Type"] = "USBTYPEAIN";
    int ability = 0;   
	for(it = abilitys.begin(); it != abilitys.end(); it++)
	{
	    string content;
        UsbAVStream::instance()->getDeviceName(it->first, content);
        content =  content + "&" + it->first;       
		detail["Content"] = content;
		
        ability = ((it -> second) & 0xff);  
        LOG_PrintInfo("getUsbAbility::%s ---> %d, Content=%s, ability=%d\n", (it -> first).c_str(), it -> second, content.c_str(), ability);
		switch(ability)
		{
            case 0x01:
                detail["StreamAbility"] = VIDEO_ONLY;
                break;
            case 0x02:
            case 0x06:
                detail["StreamAbility"] = AUDIO_ONLY;
                break;
            case 0x03:
            case 0x07:
                detail["StreamAbility"] = VIDEO_AUDIO;
                break;
            default:
                continue;
		}		
        module.append(detail);        
	}
	if(module.size() > 0)
	{
    	sType["Modules"] = module;
    	table["SupportType"].append(sType);
	}

#if 1
    ///RTSP----mdns搜寻
    sType.clear();
    module.clear();
	detail.clear();
    sType["Type"] = "RTSP";
    
    std::set<NetworkDeviceAbility> vectorNet;
    Mdns::instance()->browserNetWorkDevice(vectorNet);
    
    std::set<NetworkDeviceAbility>::iterator itNet;
    NetworkDeviceAbility devInfo;
    

    for(itNet = vectorNet.begin(); itNet != vectorNet.end(); ++itNet)
    {
        devInfo = *itNet;
        detail["StreamAbility"] =  devInfo.rtspBility;
        detail["Content"] = devInfo.serverName;

        module.append(detail);
    }

    ///test
    /*detail["StreamAbility"] =  0;
    detail["Content"] = "v520d_090M0083&rtsp://192.168.16.30:554/live/mainstream";
    module.append(detail);*/
    
    if(module.size() > 0)
	{
    	sType["Modules"] = module;
    	table["SupportType"].append(sType);
	}
#endif


#if 0
    ///BLUETOOTH----待检测
	sType.clear();
    sType["Type"] = "BLUETOOTH";
    sType["StreamAbility"] = AUDIO_ONLY;
    table["SupportType"].append(sType);
#endif

    ///LineIN----待检测
    sType.clear();
    sType["Type"] = "LINEIN";
    sType["StreamAbility"] = AUDIO_ONLY;
    table["SupportType"].append(sType);

    ///UsbTypecIN
    sType.clear();
    sType["Type"] = "USBTYPECIN";
    sType["StreamAbility"] = AUDIO_ONLY;
    table["SupportType"].append(sType);
    

    table["Result"] = true;
    
    m_supportStreamInfo = table;


    //printf("***m_supportStreamInfo=%s\n", m_supportStreamInfo.toStyledString());
    
    return true;
}

bool CurtainActManager::setPlayStream(const Json::Value &table)
{
# if 0
    StreamInfo info = {0};
    string content;
    string type;

    std::lock_guard<std::mutex> guard(m_streamMutex);
    m_playVideoStreamMap.clear();
    
	for(uint i = 0; i < table.size(); ++i)
	{
	    if((table[i].isMember("Channel")) && (table[i].isMember("Type")))
	    {
    	    info.displayChn = table[i]["Channel"].asInt();
    	    
    	    type = table[i]["Type"].asString();
    	    typeToEnum(type, info.type);
	    }

	    if(table[i].isMember("ID"))
	    {
            info.id = table[i]["ID"].asInt();
	    }

	    if((type == "OSD") && (table[i].isMember("Content")))
	    {
            content = table[i]["Content"].asString();
	        strcpy(info.content, content.c_str());
	    }

        m_playVideoStreamMap[info.displayChn] = info;
	}
#endif
    return true;
}

bool CurtainActManager::getStreamInfo(int streamType, StreamInfo* pStreamInfo, int *streamNum)
{
    bool iRet = false;
    int i = 0;

    std::lock_guard<std::mutex> guard(m_curtainMutex); //m_playVideoStreamMap与m_playVideoStreamMap操作保护

    if(streamType == 0)
    {
        *streamNum = m_playVideoStreamMap.size();
        
        if(*streamNum > MAX_STREAM_NUM)
        {
           *streamNum = MAX_STREAM_NUM;
        }

        std::map<int,StreamInfo>::iterator itVideo = m_playVideoStreamMap.begin();
        for(; itVideo != m_playVideoStreamMap.end(); ++itVideo, ++i)
        {
            if(i >= MAX_STREAM_NUM)
            {
                return true;
            }
            memcpy(pStreamInfo, &(itVideo->second), sizeof(StreamInfo));
            pStreamInfo++;
        }
        
        iRet = true;
    }
    else if(streamType == 1)
    {
        *streamNum = m_playAudioStreamMap.size();
        
        if(*streamNum > MAX_STREAM_NUM)
        {
           *streamNum = MAX_STREAM_NUM;
        }

        std::map<int,StreamInfo>::iterator itAudio = m_playAudioStreamMap.begin();
        for(; itAudio != m_playAudioStreamMap.end(); ++itAudio, ++i)
        {
            if(i >= MAX_STREAM_NUM)
            {
                return true;
            }
            memcpy(pStreamInfo, &(itAudio->second), sizeof(StreamInfo));
            pStreamInfo++;
        }
        
        iRet = true;
    }

    return iRet;
}


bool CurtainActManager::parseCurtainLayout(const Json::Value table)
{
    //LOG_PrintInfo("parseCurtainLayout table=%s\n",table.toStyledString().c_str());    
    
    if(!table.isMember("StreamSource")
      || !table.isMember("Number"))
    {
        errorf("Json params is error\n");
        return false;
    }
    
    CurtainInfo curtainInfo = {0};  
    StreamCofigInfo configInfo;
    VideoMixerInfo videoMixerInfo = {0};
    AudioMixerInfo audioMixerInfo = {0};
    StreamInfo info = {0};
    ScreenCodt codt = {0}; 
    TaskInfo task = {0};
    
    int i = 0;
    uint j = 0;
    string str;
    curtainInfo.curtainNum = table["Number"].asInt();
    curtainInfo.outNum = table["StreamSource"].size();

    if(curtainInfo.outNum == 0)
    {
        errorf("Json params is error,StreamSource outNum is 0\n");
        return false;
    }

    Json::Value streamSource = table["StreamSource"];
    Json::Value detail = Json::Value::null;
    Json::Value tmp = Json::Value::null; 

    m_interfaceVectorMap[curtainInfo.curtainNum].clear();
    
    for(i = 0; i < curtainInfo.outNum; ++i)
    {   
        ///输出接口类型
        if((!streamSource.isArray()) 
            || (!streamSource[i].isMember("OutputType")))
        {
            errorf("Json params is error\n");
            continue;
        }

        memset(&configInfo, 0, sizeof(StreamCofigInfo));
        
        str = streamSource[i]["OutputType"].asString();
        outputToEnum(str, &configInfo.interface); 
        m_interfaceVectorMap[curtainInfo.curtainNum].emplace_back(configInfo.interface);
        
        ///视频拼接信息解析
        if(streamSource[i].isMember("VideoMixer"))
        {
            if((!streamSource[i]["VideoMixer"].isMember("Detail")) || (!streamSource[i]["VideoMixer"].isMember("Width"))
                || (!streamSource[i]["VideoMixer"].isMember("Height")) || (!streamSource[i]["VideoMixer"].isMember("Fps")))
            {
                errorf("Json params is error\n");
                return false;
            }

            memset(&videoMixerInfo, 0, sizeof(videoMixerInfo));
            
            videoMixerInfo.displayWidth = streamSource[i]["VideoMixer"]["Width"].asInt();
            videoMixerInfo.displayHeight = streamSource[i]["VideoMixer"]["Height"].asInt();
            videoMixerInfo.displayFps = streamSource[i]["VideoMixer"]["Fps"].asInt();

            detail = streamSource[i]["VideoMixer"]["Detail"];
            videoMixerInfo.totalPictures = detail.size();

            LOG_PrintInfo("Interface:%d,OutputType:%s, VideoMixer Detail size:%d\n",configInfo.interface, str.c_str(),detail.size());
            bool isValid = false;
            for(j = 0; j < detail.size(); ++j)
            {
                if((!streamSource.isArray())
                || (!detail[j].isMember("Stream")) || (!detail[j].isMember("Position"))
                || (!detail[j].isMember("Layer")) || (!detail[j].isMember("Picture"))) //(!detail[j].isMember("Task"))
                {
                    continue;
                }

                videoMixerInfo.videoInfo[j].pictureNum = detail[j]["Picture"].asInt();
                videoMixerInfo.videoInfo[j].layerNum = detail[j]["Layer"].asInt();
                
                tmp = detail[j]["Stream"];
                if((tmp.isMember("Channel")) && (tmp.isMember("Type")))
                {
                    memset(&info, 0, sizeof(StreamInfo));
                    
            	    info.displayChn = tmp["Channel"].asInt();
            	    str = tmp["Type"].asString();
                    if(str.empty())
                    {
                        continue;
                    }
            	    
            	    typeToEnum(str, &info.type);

            	    LOG_PrintInfo("type:%s, info.type:%d\n", str.c_str(),info.type);
            	    
            	    if(tmp.isMember("Content"))
            	    {
                        const char* str = tmp["Content"].asCString();
                        
                        int len = sizeof(info.content)/sizeof(char);
                        strncpy(info.content, str, len-1);
                        info.content[len -1] = '\0';  
            	    }

            	    videoMixerInfo.videoInfo[j].videoStream = info;
                }
                else
                {
                    errorf("Json params is error\n");
                    return false;
                }
                
                tmp = detail[j]["Position"];
                if((tmp.isMember("Left")) && (tmp.isMember("Top"))
                && (tmp.isMember("Width")) && (tmp.isMember("Height")))
                {
            	    codt.left = tmp["Left"].asInt();
            	    codt.top = tmp["Top"].asInt();
            	    codt.width = tmp["Width"].asInt();
            	    codt.height = tmp["Height"].asInt();
            	    videoMixerInfo.videoInfo[j].codt = codt;
                }
                else
                {
                    errorf("Json params is error\n");
                    return false;
                }
            #ifdef TASK_INFO
                if(detail[j].isMember("Task"))
                {
                    tmp = detail[j]["Task"];
                    if((tmp.isMember("Sequence")) && (tmp.isMember("Start"))
                    && (tmp.isMember("Stop")))
                    {
                	    task.Sequence = tmp["Sequence"].asInt();
                	    task.StartTime = tmp["Start"].asInt();
                	    task.StopTime = tmp["Stop"].asInt();
                	    videoMixerInfo.videoInfo[j].task = task;
                    }
                }
            #endif

                isValid = true;
            }

            //if(isValid) //视频目前通道需要从0开始，暂不过滤
            configInfo.videoMixerInfo = videoMixerInfo;
        }

        ///音频混音信息解析
        if(streamSource[i].isMember("AudioMixer"))
        {
            if(!streamSource[i]["AudioMixer"].isMember("Detail"))
            {
                errorf("Json params is error\n");
                return false;
            }

            memset(&audioMixerInfo, 0, sizeof(audioMixerInfo));

            if((streamSource[i]["AudioMixer"].isMember("SampleRate"))
                && (streamSource[i]["AudioMixer"].isMember("ChannelNum")))
            {
                audioMixerInfo.sampleRate = streamSource[i]["AudioMixer"]["SampleRate"].asInt();
                audioMixerInfo.channelNum = streamSource[i]["AudioMixer"]["ChannelNum"].asInt();
            }
            else
            {
                getOutputInfo(configInfo.interface, &audioMixerInfo.sampleRate, &audioMixerInfo.channelNum);
            }

            detail = streamSource[i]["AudioMixer"]["Detail"];
            audioMixerInfo.totalInput = detail.size();

            LOG_PrintInfo("Interface:%d,OutputType:%s, AudioMixer Detail size:%d\n",configInfo.interface, str.c_str(),detail.size());

            bool isValid = false;
            for(j = 0; j < detail.size(); ++j)
            {
                if(!detail[j].isMember("Stream"))
                {
                    continue;
                }
                
                tmp = detail[j]["Stream"];
                if((tmp.isMember("Channel")) && (tmp.isMember("Type")))
                {
                    memset(&info, 0, sizeof(StreamInfo));
                    
                    info.displayChn = tmp["Channel"].asInt();
                    
            	    str = tmp["Type"].asString();
            	    if(str.empty())
                    {
                        continue;
                    }
            	    typeToEnum(str, &info.type);

            	    LOG_PrintInfo("info.type:%d, displayChn:%d\n", info.type, info.displayChn);            	    
            	    if(tmp.isMember("Content"))
            	    {
                        const char* str = tmp["Content"].asCString();                        
                        int len = sizeof(info.content)/sizeof(char);
                        strncpy(info.content, str, len-1);
                        info.content[len -1] = '\0';  
            	    }

            	    audioMixerInfo.audioInfo[j].audioStream = info;
                }
                else
                {
                    errorf("Json params is error\n");
                    return false;
                }

                isValid = true;
           }
           
           if(isValid)
                configInfo.audioMixerInfo = audioMixerInfo;
       }

       curtainInfo.cofigInfo[i] = configInfo;
    }

	m_curtainInfoMap[curtainInfo.curtainNum] = curtainInfo;

	m_playCurtainTable = table;

	LOG_PrintInfo("curtainInfo.curtainNum:%d parse success\n", curtainInfo.curtainNum);

	return true;
}

bool CurtainActManager::setCurtainLayout(const Json::Value &curtainTable, bool rwFlg){
    LOG_PrintInfo("setCurtainLayout curtainTable=%s\n",curtainTable.toStyledString().c_str());        
    //根据传入的动作是删除还是增加执行不一样的操作
    //判断参数
    if(!curtainTable.isMember("Action") || !curtainTable["Action"].isBool()){
    	LOG_PrintError("Params Parse Error!!!\n");
    	return false;
    }
    bool action = curtainTable["Action"].asBool();
    if(!curtainTable.isMember("Number") || !curtainTable["Number"].isInt()){
		LOG_PrintError("Params Parse Error!!!\n");
		return false;
	}
	
    int number = curtainTable["Number"].asInt();
    Json::Value table = curtainTable;
    if(!action)
    {
    	//如果执行的是删除操作
    	return removeCurtainJson(number);
    }
    else
    {
        //保存或读取操作
    	readWriteCurtainJson(table, rwFlg);
    }

    //usb源更新切换
    if(number == RoomsDefaultMeeting 
      || number == AirDefaultMeeting
      || number == StreamerNum)
    {
        usbStreamCheck(table);
    }

    //解析场景信息
    return parseCurtainLayout(table);

}


int getMainRtspChannel(int index){
    while(true){
        index++;
        if(index >= MAX_INTERFACE_NUM){
            return 0;
        }

        if(index != RTSP_SUB_OUT4 && index != RTSP_SUB_OUT5 
            && index != RTSP_SUB_OUT6 && index != RTSP_SUB_OUT7){
            return index;
        }
    }
    
}

bool CurtainActManager::removeCurtainJson(int curtain_number){
	//打开文件
	Json::Value curtainTable;
	getJsonTable(configPathCurtain, curtainTable);

	//获取到layouts遍历当遇到编号相同的幕墙的时候删除
	if(!curtainTable.isMember("Layouts") || !curtainTable["Layouts"].isArray()){
		LOG_PrintError("faild to read json Layouts\n");
		return false;
	}
	Json::Value layouts = curtainTable["Layouts"];
	for(uint i = 0; i < layouts.size(); i++){
		LOG_PrintInfo("layout[%d]---%s\n", i ,layouts[i].toStyledString().c_str());
		if(!layouts[i].isMember("Number") || !layouts[i]["Number"].isInt()){
			LOG_PrintError("json data format invalid\n");
			return false;
		}
		int number = layouts[i]["Number"].asInt();
		if(number == curtain_number){
			Json::Value remove;
			layouts.removeIndex(i, &remove);
			break;
		}
	}
	Json::Value ret;
	ret["Layouts"] = layouts;
	setJsonTable(configPathCurtain, ret);
	LOG_PrintInfo("CurtainActManager::readWriteCurtainJson(const Json::Value curtain) end\n");
	return true;
}

bool CurtainActManager::readWriteCurtainJson(Json::Value& curtain, bool rwFlg){
	LOG_PrintInfo("CurtainActManager::readWriteCurtainJson(const Json::Value curtain) start\n");
	int curtainNumber;
	uint i = 0;
	//获取当前幕墙设置的编号
	if(!curtain.isMember("Number") || !curtain["Number"].isInt()){
		LOG_PrintError("json data format invalid\n");
		return false;
	}
	curtainNumber = curtain["Number"].asInt();

	//获取当前配置文件中的所有配置
	Json::Value curtainTable;
	
#if defined(MODEL_ROOMS) || defined(MODEL_AIR)	
    getJsonTable(configPathCurtain, curtainTable);
#else
    getJsonTable(defaultConfigPathCurtain, curtainTable); //TAIL读取系统user配置
    LOG_PrintInfo("json data from defaultConfigPathCurtain\n");
#endif

	//读取文件中存储的所有场景，遍历当前的的幕墙编号是否存在，如果存在就直接覆盖
	if(!curtainTable.isMember("Layouts") || !curtainTable["Layouts"].isArray()){
		LOG_PrintError("faild to read json Layouts\n");
		return false;
	}
	Json::Value layouts = curtainTable["Layouts"];
	
	//遍历结束之后不存在就在配置我呢见中添加一项
	for(; i < layouts.size(); i++){
		//LOG_PrintInfo("layout[%d]---%s\n", i ,layouts[i].toStyledString().c_str());
		if(!layouts[i].isMember("Number") || !layouts[i]["Number"].isInt()){
			LOG_PrintError("json data format invalid\n");
			return false;
		}
		int number = layouts[i]["Number"].asInt();
		if(number == curtainNumber)
		{
		    if(!rwFlg) //获取配置
            {
                curtain = layouts[i];
                LOG_PrintInfo("CurtainActManager::readWriteCurtainJson curtainNumber:%d read success, curtain=%s\n", curtainNumber, curtain.toStyledString().c_str());
                return true;
            }
            else
            {
			    layouts[i] = curtain; //保存配置
			}
			break;
		}
	}

	//获取当前幕墙的Json配置信息
	if(!curtain.isMember("StreamSource")){
		LOG_PrintError("json data format invalid\n");
		return false;
	}
	
	//添加结束之后返回
	if(i == layouts.size()){
		layouts.append(curtain);
	}
	Json::Value ret;
	ret["Layouts"] = layouts;
	setJsonTable(configPathCurtain, ret);
	LOG_PrintInfo("CurtainActManager::readWriteCurtainJson(const Json::Value curtain) end\n");
	return true;
}

bool CurtainActManager::getCurtainLayout(Json::Value &table){
	//读取配置文件直接赋值返回
	return getJsonTable(configPathCurtain, table);
}

bool CurtainActManager::getCurtainLayout(CurtainInfo* curtainInfo)
{
    
    *curtainInfo = m_playCurtainInfo;

    return true;
}

bool CurtainActManager::getCurtainPlayState(PlayState *state)
{
    *state = m_playState;

    return true;
}


bool CurtainActManager::playDefaultCurtain(){
    Json::Value root2 = Json::Value::null;
   int defaultCurtain; 
    #ifdef MODEL_AIR
        defaultCurtain = AirDefaultMeeting;
    #else
        defaultCurtain = RoomsDefaultMeeting;
    #endif
    root2["Number"] = defaultCurtain;
	root2["PlayMode"] = 0;
	root2["Action"] = 1;
	if(!setPlayStrategy(root2)){
        return false;
    }
    return true;
}

bool CurtainActManager::setPlayStrategy(const Json::Value &table)
{
    printf("setPlayStrategy table=%s\n",table.toStyledString().c_str());
    if((!table.isMember("Number")) || (!table.isMember("PlayMode"))
        || (!table.isMember("Action")))
    {
        errorf("Json params is error\n");
        return false;
    }

    int num = table["Number"].asInt();
    int action = table["Action"].asInt();
    int mode = table["PlayMode"].asInt();

	///其他场景抢占数字标牌时回收资源
	if(num != StreamerNum && m_playCurtainNum == StreamerNum){
		StreamerCurtainPlay::instance()->stopStreamerCurtain();
	}
	
    ///默认场景读配置获取
    if((num > CustomNum) && (action == 1) )
    {
        Json::Value curtainTable = Json::Value::null;
        curtainTable["Number"] = num;
        curtainTable["Action"] = true;
        
        setCurtainLayout(curtainTable, false);//读取和解析配置   
    }

    if(m_curtainInfoMap.count(num) == 0)
    {
        errorf("curtainNum:%d is not exist\n", num);
        return false;
    }

    PlayStrategy strategy = {0};
    strategy.curtainNum = num;    
    strategy.playMode = mode;
    strategy.action = action;

    int channel = 0;
    StreamInfo stream = {0};
    TaskInfo task = {0};
    std::lock_guard<std::mutex> guard(m_curtainMutex);

    if(m_playState == RUNNING)
    {
        
        m_curStrategy.action = 0;
        parseCurtainStrategy(m_curStrategy); //停止播放当前幕墙

        m_playState = IDLE;

        usleep(100*1000);

    }  

    if(strategy.action == 1) 
    {
        m_playCurtainInfo = m_curtainInfoMap[num]; //重新设置当前幕墙
        m_curStrategy = strategy;

        saveCurPlayNum(num);//保存当前在播放的场景编号到配置中
        
        StreamCofigInfo configInfo;
        VideoMixerInfo videoMixerInfo = {0};
        AudioMixerInfo audioMixerInfo = {0};
        StreamOutInterface interface;
        m_usbVideoInFlg = 0;
        
        
        
        m_playVideoStreamMap.clear();
        m_playVideoTaskMap.clear();
        m_playAudioStreamMap.clear();
        m_playStreamMap.clear();
        
        int i = 0;
        int j = 0;
        bool audioBaseFlag = false;
        uint8_t audioTotal = 0;
        uint8_t maxAiChannel = 0;
        
        for(i = 0; i < m_playCurtainInfo.outNum; ++i)
        {
            memset(&configInfo, 0, sizeof(configInfo));
            
            configInfo = m_playCurtainInfo.cofigInfo[i];
            
            videoMixerInfo = configInfo.videoMixerInfo;
            audioMixerInfo = configInfo.audioMixerInfo;
            interface = configInfo.interface;

            for(j = 0; j < videoMixerInfo.totalPictures; ++j)
            {
                stream = videoMixerInfo.videoInfo[j].videoStream;
                task = videoMixerInfo.videoInfo[j].task;
                channel = stream.displayChn;     
                
                m_playVideoStreamMap[channel] = stream; //重新设置播放视频流

                if(stream.type == USBTYPEAIN_STREAM)
                {
                    if(interface == BYOM_OUT)
                    {
                        m_usbVideoInFlg |= 0x01;
                    }
                    else if(interface == USBTYPEC_OUT)
                    {
                        m_usbVideoInFlg |= 0x02;
                    }
                    else
                    {
                        m_usbVideoInFlg |= 0x04;
                    }
                }
                
            #ifdef TASK_INFO
                m_playVideoTaskMap[channel] = task;
            #endif
            }
            
            for(j = 0; j < audioMixerInfo.totalInput; ++j)
            {
                stream = audioMixerInfo.audioInfo[j].audioStream;
                channel = stream.displayChn;   
           
                m_playAudioStreamMap[channel] = stream; //重新设置播放音频流

                if(stream.type == LINEIN_STREAM)
                {
                    audioBaseFlag = true;
                }
                else if(stream.type != MIRROR_STREAM)
                {
                    audioTotal++;

                    if(channel > maxAiChannel)
                    {
                        maxAiChannel = channel; //获取当前配置除了投屏音频外通道最大值
                    }                    
                }
            }

            //LOG_PrintInfo("*****test enter,videoMixerInfo.totalPictures=%d, audioMixerInfo.totalInput=%d\n",videoMixerInfo.totalPictures, audioMixerInfo.totalInput);

            LOG_PrintInfo("OutNum[%d]-->interface=%d, m_playVideoStreamMap: %d,  m_playAudioStreamMap: %d, audioBaseFlag:%d\n",i,configInfo.interface, m_playVideoStreamMap.size(), m_playAudioStreamMap.size(), audioBaseFlag);
        }

        ///当场景中无LINEIN配置时，动态添加作为音频基准
        if(!audioBaseFlag && audioTotal > 0)
        {
            channel = maxAiChannel + 1;
            stream.displayChn = channel;
            stream.type = LINEIN_STREAM; 
 
            m_playAudioStreamMap[channel] = stream;
        }
        

        m_playCurtainNum = num;
        m_playState = RUNNING;
        parseCurtainStrategy(m_curStrategy); //开始播放新幕墙场景

      
    }

    return true;
}

bool CurtainActManager::SetDeviceShareStatus(const Json::Value &table)
{
    printf("SetDeviceShareStatus table=%s\n", table.toStyledString().c_str());
    if (!table.isMember("Status"))
    {
        errorf("Json params Status is error\n");
        return false;
    }

    string deviceStrUrl;
    int    deviceStrNum = 0;
    bool   deviceStatus = table["Status"].asBool();
    if (!deviceStatus)
    {
        if (!table.isMember("ShareStreamUrl")) 
        {
            errorf("Json params ShareStreamUrl is error\n");
            return false;
        }
        else
        {
            deviceStrUrl = table["ShareStreamUrl"].asString();
            deviceStrNum = DeviceStsSlave;
        }
    }
    else 
    {
        deviceStrNum = DeviceStsMaster;
    }

    Json::Value curtainTable;
    if (!getSpecificNumCurtain(curtainTable, deviceStrNum)) {
        LOG_PrintError("Default Streamer Curtain get faild!!\n");
        return false;
    }
    
    if (!deviceStatus) 
    {
        if (!curtainTable.isMember("StreamSource"))
        {
            LOG_PrintError("curtainTable StreamSource get faild!!\n");
            return false;
        }

        Json::Value streamSource = curtainTable["StreamSource"];
        if (!streamSource.isArray())
        {
            LOG_PrintError("streamSource isArray faild!!\n");
            return false;
        }

        Json::Value stream0 = streamSource[0];
        if (!stream0.isMember("VideoMixer"))
        {
            LOG_PrintError("VideoMixer AudioMixer get faild!!\n");
            return false;
        }

        stream0 = stream0["VideoMixer"];
        if (!stream0.isMember("Detail") )
        {
            LOG_PrintError("Json Detail get faild!!\n");
            return false;
        }

        stream0 = stream0["Detail"];
        if (!stream0.isArray())
        {
            LOG_PrintError("Json isArray get faild!!\n");
            return false;
        }

        stream0 = stream0[0];
        if (!stream0.isMember("Stream"))
        {
            LOG_PrintError("Json Stream get faild!!\n");
            return false;
        }

        stream0 = stream0["Stream"]; 
        if (!stream0.isMember("Type") || !stream0.isMember("Content"))
        {
            LOG_PrintError("Json Type  Content get faild!!\n");
            return false;
        }

        /* content is set online stream url */
        curtainTable["StreamSource"][0]["VideoMixer"]["Detail"][0]["Stream"]["Type"] = "RTSP";
        curtainTable["StreamSource"][0]["VideoMixer"]["Detail"][0]["Stream"]["Content"] = deviceStrUrl.c_str();
    }

    setCurtainLayout(curtainTable);

    Json::Value root2 = Json::Value::null;
    root2["Number"] = deviceStrNum;
    root2["PlayMode"] = 0;
    root2["Action"] = 1;
    setPlayStrategy(root2);

    return true;
}

bool CurtainActManager::parseCurtainStrategy(PlayStrategy strategy)
{   
    uint i = 0;
    uint j = 0;
    uint videoNum = 0;
    StreamPlayInfo playInfo;
    StreamInfo stream = {0};
    StreamInType type;
	char content[256] = {0};

	static std::vector<StreamOutInterface> s_outInterface;

    ///分析输入流
	if(strategy.action == 1)
	{
        int index = 0;
        int maxIndex;
        std::map<int,StreamInfo>::iterator itVideo = m_playVideoStreamMap.begin();
        for(; itVideo != m_playVideoStreamMap.end(); ++itVideo)
        {
            index = itVideo->first;
            stream = itVideo->second;

            memset(&playInfo, 0, sizeof(playInfo));
            playInfo.stream = stream;
            playInfo.playAbility = VIDEO_ONLY;
            playInfo.videoChn = stream.displayChn;
            
        #ifdef TASK_INFO
            playInfo.task = m_playVideoTaskMap[index];
        #endif
        
            m_playStreamMap[index] =  playInfo; //存储纯视频播放信息
            maxIndex = index > maxIndex ? index : maxIndex;
        }
        
        int indexAudio = 0;
        bool sameStreamFlg = false;
        std::map<int,StreamInfo>::iterator itAudio = m_playAudioStreamMap.begin();
        for(; itAudio != m_playAudioStreamMap.end(); ++itAudio)
        {
            indexAudio = itAudio->first;
            type = (itAudio->second).type;
            memset(content, 0, sizeof(content)/sizeof(char));
            strcpy(content, (itAudio->second).content);

            sameStreamFlg = false;
            if((type == LINEIN_STREAM)
                || (type == BLUETOOTH_STREAM) 
                || (type == MIC_STREAM)
                || (type == USBTYPECIN_STREAM))
            {
                 //纯音频接口
            }
            else
            {
                for(itVideo = m_playVideoStreamMap.begin(); itVideo != m_playVideoStreamMap.end(); ++itVideo)
                {
                    index = itVideo->first;
                    stream = itVideo->second;

                    if((type == stream.type) 
                    && (strcmp(content, stream.content) == 0))
                    {
                        m_playStreamMap[index].playAbility = VIDEO_AUDIO;
                        m_playStreamMap[index].audioChn = indexAudio; //在原来基础上添加音频播放信息

                        sameStreamFlg = true;
                        break;
                    } 
                }
            }

            if(!sameStreamFlg)
            {
                memset(&playInfo, 0, sizeof(playInfo));
                playInfo.stream = (itAudio->second);
                playInfo.playAbility = AUDIO_ONLY;
                playInfo.audioChn = playInfo.stream.displayChn;
                
                m_playStreamMap[++maxIndex] =  playInfo; //往后存储纯音频播放信息
            }
        }


    	///开启输出接口
    	int curtainNum = strategy.curtainNum;
        uint8_t outNum = m_interfaceVectorMap[curtainNum].size();   
        if(outNum <= 0)
        {
            LOG_PrintWarn("StreamOutInterface is NULL\n");
            return false;
        }
        vector<StreamOutInterface>::iterator it = m_interfaceVectorMap[curtainNum].begin();
        for(; it != m_interfaceVectorMap[curtainNum].end(); ++it)
        {
            dealOutInterface(*it, strategy);

            LOG_PrintInfo("OutInterface open type=%d\n", *it);
        }
        s_outInterface.clear();
        s_outInterface = m_interfaceVectorMap[curtainNum];

        ///开启输入流
        std::map<int, StreamPlayInfo>::iterator itPlay = m_playStreamMap.begin();
        for(; itPlay != m_playStreamMap.end(); ++itPlay)
        {
            playInfo = itPlay->second;

            LOG_PrintInfo(" InputStream OpenSize:%d, m_playStreamMap[%d]--> type:%d, playAbility: %d\n", m_playStreamMap.size(), itPlay->first, playInfo.stream.type, playInfo.playAbility);

            dealPlayStream(itPlay->first, playInfo, strategy);
        } 
        
    }
    else
    {
        ///关闭输入流
        std::map<int, StreamPlayInfo>::iterator itPlay = m_playStreamMap.begin();
        for(; itPlay != m_playStreamMap.end(); ++itPlay)
        {
            playInfo = itPlay->second;

            LOG_PrintInfo(" InputStream CloseSize:%d, m_playStreamMap[%d]--> type:%d, playAbility: %d\n", m_playStreamMap.size(), itPlay->first, playInfo.stream.type, playInfo.playAbility);

            dealPlayStream(itPlay->first, playInfo, strategy);
        } 

        ///关闭输出接口
        vector<StreamOutInterface>::iterator it = s_outInterface.begin();
        for(; it != s_outInterface.end(); ++it)
        {
            dealOutInterface(*it, strategy);

            LOG_PrintInfo("OutInterface close type=%d\n", *it);
        }
    }

    return true;
}

bool CurtainActManager::dealPlayStream(int index, StreamPlayInfo playInfo, PlayStrategy strategy)
{
    //LOG_PrintInfo("test enter\n");
    int action = strategy.action;
    int playMode = strategy.playMode;
    int curtainNum = strategy.curtainNum;
    StreamInType type = playInfo.stream.type;
    StreamAbility playAbility = playInfo.playAbility;

    if(playMode == 0) //0--实时,RealtimePlay， 1--按任务播放
    {
        playInfo.task.StartTime = 0;
        playInfo.task.StopTime = -1;
    }

    switch(type)
    {        
        /*case MIRROR_STREAM:
        {
            //LOG_PrintInfo("test enter\n");
            if(action == 0)
            {
                ScreenMirrorStream::instance()->stop();
            }
            else if(action == 1)
            {
                ScreenMirrorStream::instance()->start(playInfo);
            }
            break;
        }*/
        case BYOM_STREAM:
        {
            /*if(action == 0)
            {
                ScreenMirrorClient::instance()->stop();
            }
            else if(action == 1)
            {
                ScreenMirrorClient::instance()->start(playInfo);
            }*/
            break;
        }
        case PICTUREFILE_STREAM:
        {
            if(action == 0)
            {
                PictureFileStream::instance()->stop();
                //LOG_PrintInfo("test enter\n");
            }
            else if(action == 1)
            {
                PictureFileStream::instance()->start(playInfo, curtainNum);
                //LOG_PrintInfo("test enter\n");
            }
            break;
        }              
        case RTSP_STREAM:
        {
            //LOG_PrintInfo("test enter\n");
            if(action == 0)
            {
                RtspClientStream::instance(index)->stop();
            }
            else if(action == 1)
            {
                RtspClientStream::instance(index)->start(playInfo);
            }
            break;
        }
        /*case VIDEOFILE_STREAM:
        {
            //LOG_PrintInfo("test enter\n");
            if(action == 0)
            {
                VideoFileStream::instance(index)->stop();
            }
            else if(action == 1)
            {                                                      
                VideoFileStream::instance(index)->start(playInfo);
            }
            break;
        }*/ 
        case VIDEOFILE_STREAM:
        case ONLINEMP4_STREAM:
        {            
            //LOG_PrintInfo("test enter\n");
            Mp4StreamType mp4Type = MP4_ONLINE_STREAMER;
            if(type == VIDEOFILE_STREAM) 
            {
                mp4Type = MP4_LOCAL_STREAMER;
            }
            if (action == 0)
            {
                Mp4ClientStream::instance(mp4Type)->stop();
            }
            else if (action == 1)
            {
                std::string mp4VpnAddr;
                StreamerCurtainPlay::instance()->getMp4VpnValue(mp4VpnAddr);
                
                Mp4ClientStream::instance(mp4Type)->setVpnAddr(mp4VpnAddr);
                Mp4ClientStream::instance(mp4Type)->start(playInfo);
            }
            break;
        }
        case USBTYPEAIN_STREAM:
        {
            //LOG_PrintWarn("test enter\n");
            
            if(action == 0)
            {
                UsbInStream::instance(playInfo.stream.content)->stop(true);
            }
            else if(action == 1)
            {
                UsbInStream::instance(playInfo.stream.content)->start(playInfo);
            }
            break;
        }
        
        case LINEIN_STREAM:
        {
            index = playInfo.audioChn;
            if(action == 0)
            {
                AudioInMgr::instance(index)->stop();
            }
            else if(action == 1)
            {
                AudioInDesc inDesc = {0};
                inDesc.card = 0;
                inDesc.channel = index;
                AudioInMgr::instance(index)->createAudioIn(inDesc);
                
                AudioInAttr format = {0};
                string iNode;
                getSoundNode("MicArray_L", iNode);
                memcpy(format.pcAudioNode, iNode.c_str(), iNode.size());                
        	    format.enSampleFormat = SAMPLE_FMT_S16;               	
            	format.enAiLayout = AI_NORMAL;
            	format.u32SampleRate = 48000;
            	format.u32Channels = 2;
            	format.u32NbSamples = 768;
            	format.source = LINE_IN_TYPE;

            	AudioInMgr::instance(index)->setFormat(format);
                AudioInMgr::instance(index)->start();
            }
            break;
        }       
        case HDMIIN_STREAM:
        {
            if(playAbility != VIDEO_ONLY)
            {
                index = playInfo.audioChn;
                if(action == 0)
                {
                    AudioInMgr::instance(index)->stop();
                }
                else if(action == 1)
                {

                    AudioInDesc inDesc = {0};
                    inDesc.card = 0;
                    inDesc.channel = index;
                    AudioInMgr::instance(index)->createAudioIn(inDesc);

                    
                    AudioInAttr format = {0};
                    string iNode;
                    getSoundNode("rockchip_hdmiin", iNode);
                    memcpy(format.pcAudioNode, iNode.c_str(), iNode.size());  
            	    format.enSampleFormat = SAMPLE_FMT_S16;               	
                	format.enAiLayout = AI_NORMAL;
                	format.u32SampleRate = 48000;
                	format.u32Channels = 2;
                	format.u32NbSamples = 768;
                	format.source = HDMI_IN_TYPE;

                	AudioInMgr::instance(index)->setFormat(format);
                    AudioInMgr::instance(index)->start();
                }
            }
            break;
        }
        case USBTYPECIN_STREAM:
        {
            if(action == 0)
            {
                MEDIA_UacInStop();
            }
            else if(action == 1)
            {
                MEDIA_UacInStart(playInfo.audioChn);
            }
            break;
        }
        case INSIDE_STREAM:
        case OSD_STREAM:
        default:
            break;

    }

    return true;
}

bool CurtainActManager::getOutputInfo(StreamOutInterface type, int *sampleRate, int *channels)
{
    switch(type)
    {        
        case USBTYPEA_OUT1:
        {
            string usbPort = UsbAVStream::instance()->USB_IN_1;
            
            UsbInStream::instance(usbPort)->getOutputInfo(type, usbPort, sampleRate, channels);

            LOG_PrintInfo("test enter,type=%d, sampleRate=%d, channels=%d\n", type, *sampleRate, *channels);
            
            break;
        }
        case USBTYPEA_OUT2:
        {
            string usbPort = UsbAVStream::instance()->USB_IN_2;
            UsbInStream::instance(usbPort)->getOutputInfo(type, usbPort, sampleRate, channels);

            LOG_PrintInfo("test enter,type=%d, sampleRate=%d, channels=%d\n", type, *sampleRate, *channels);
            
            break;
        }
        case USBTYPEC_OUT:
        {
            *sampleRate = 16000;
            *channels = 1;
            LOG_PrintInfo("test enter,type=%d, sampleRate=%d, channels=%d\n", type, *sampleRate, *channels);
            break;
        }
        case BYOM_OUT:
        case MIRROR_OUT:
        {
            *sampleRate = 48000;
            *channels = 1;
            LOG_PrintInfo("test enter,type=%d, sampleRate=%d, channels=%d\n", type, *sampleRate, *channels);
            break;
        }
        case HDMI_OUT:
        case LINE_OUT:
        {
            *sampleRate = 48000;
            *channels = 4;
            LOG_PrintInfo("test enter,type=%d, sampleRate=%d, channels=%d\n", type, *sampleRate, *channels);
            break;
        }
        default:
            break;
    }
    return true;
}

bool CurtainActManager::dealOutInterface(StreamOutInterface type, PlayStrategy strategy)
{
    int action = strategy.action;
    switch(type)
    {        
        case USBTYPEA_OUT1:
        {
            string usbPort = UsbAVStream::instance()->USB_IN_1;
            if(action == 0)
            {
                UsbInStream::instance(usbPort)->outputStop(type, usbPort, true);
            }
            else if(action == 1)
            {
                UsbInStream::instance(usbPort)->outputStart(type, usbPort);
            }
            break;
        }
        case USBTYPEA_OUT2:
        {
            string usbPort = UsbAVStream::instance()->USB_IN_2;
            if(action == 0)
            {
                UsbInStream::instance(usbPort)->outputStop(type, usbPort, true);
            }
            else if(action == 1)
            {
                UsbInStream::instance(usbPort)->outputStart(type, usbPort);
            }
            break;
        }
        case USBTYPEC_OUT:
        {
            /*int status = MEDIA_UvcInit();
            if (status)
            {
                LOG_PrintError("Fail to MEDIA_UvcInit!\n");
            }*/
            break;
        }
        case BYOM_OUT:       
        {
            if(action == 0)
            {
                ScreenMirrorStream::instance()->outputStop();
            }
            else if(action == 1)
            {
                ScreenMirrorStream::instance()->outputStart();
            }
            break;
        }
        case MIRROR_OUT:
        {
            /*if(action == 0)
            {
                ScreenMirrorClient::instance()->outputStop();
            }
            else if(action == 1)
            {
                ScreenMirrorClient::instance()->outputStart();
            }*/
            break;
        }
        case SD_OUT:
        {
            if(action == 0)
            {
                MEDIA_RecorderStop_Core();
            }
            else if(action == 1)
            {
                MEDIA_RecorderStart_Core();
            }
            
            break;
        }
        default:
            break;
    }

    return true;
}

bool CurtainActManager::getDisplayinfo(const Json::Value table, std::string &info)
{
    std::string value = "DevPasswd.Keys";
    Json::Value Config;
    bool ret = IConfigInterface::GetInstance()->Get(value, Config);
    if(!ret)
    {
        return false; 
    }

    //printf("Config::instance()->Get() Config=%s\n",Config.toStyledString().c_str());

    string content;
    string keys = Config.asString();
    if(keys.size() == 0)
    {
        content = "QUICK SETUP %Please connect to AP NearHub_Rooms %and set up AP from a desktop computer";
    }
    else
    {
        string ssid;
        value = "Wifi.SSID";
        ret = IConfigInterface::GetInstance()->Get(value, Config);
        if(!ret)
        {
            return false; 
        }
        //printf("Config::instance()->Get() Config=%s\n",Config.toStyledString().c_str());
        ssid = Config.asString();

        string name;
        if(table.isMember("Name"))
        {
            name = table["Name"].asString();
        }
        else
        {
            value = "DevName.Name";
            ret = IConfigInterface::GetInstance()->Get(value, Config);
            if(!ret)
            {
                return false; 
            }
            name = Config.asString();
        }
        
        content = "PRESENT WIRELESSLY %network: %" + ssid
                   +   " %device name: %" + name;
    }

    info = content;

    LOG_PrintInfo("getDisplayinfo::info=%s\n",info.c_str());

    return true;
}

bool CurtainActManager::playStartUpCurtain(const Json::Value table)
{
#if defined(MODEL_ROOMS) || defined(MODEL_AIR)

    ///ROOMS & AIR
  #ifndef MULTICAMERA_CUSTOMER  

    ScreenMirrorStream::instance()->HdmioutControl(0); //使能HDMIOUT

    {
        ///启动投屏接收服务
        StreamPlayInfo playInfo;
        StreamInfo stream;
        stream.type = MIRROR_STREAM;
        strcpy(stream.content, "private");

        playInfo.playAbility = VIDEO_AUDIO;
        playInfo.stream = stream;
    	playInfo.videoChn = 7;//15
    	playInfo.audioChn = 7;
    	
        ScreenMirrorStream::instance()->start(playInfo);
    }

#if 1
    {
        ///启动BGM播放任务
        if(BgmListManager::Instance()->isBgmCurtainExist())
        {
            LOG_PrintInfo("playBgmCurtain need \n");
            Media::BgmCurtainPlay::instance()->playBgmCurtain();
        }
    }
#endif

    int playNum = 0;    
    getCurPlayNum(&playNum); //获取当前或上次断电前的场景编号

    LOG_PrintInfo("getStartUp playNum = %d\n", playNum);

    if(playNum < 0)
    {
    #if defined(MODEL_ROOMS)
        playNum = RoomsDefaultMeeting; //默认开会场景
    #else
        playNum = AirDefaultMeeting; //默认开会场景
    #endif
    }
    else if((playNum == CustomNum)) //默认背景图
    {        
        static bool startupFlg = true;

        if(!startupFlg 
        && (m_playState != RUNNING) 
        && (m_playCurtainNum != CustomNum))
        {
            return false;
        }

        startupFlg = false;
        
        Json::Value root = Json::Value::null;    
        root["Number"] = CustomNum;
        root["Action"] = true;
        root["CurtainName"] = "StartUpCurtain";


        Json::Value stream = Json::Value::null;
        stream["OutputType"] = "USBTYPECOUT"; //USBTYPECOUT //HDMIOUT

        Json::Value videoMixer = Json::Value::null;
        videoMixer["Width"] = 1920;
        videoMixer["Height"] = 1080;
        videoMixer["Fps"] = 30;    
        
        Json::Value video = Json::Value::null;
        video["Picture"] = 0;
        video["Layer"] = 1;
        video["Stream"]["Channel"] = 0;
        video["Stream"]["Type"] = "PICTUREFILE";
        video["Stream"]["Content"] = "startup.jpg";
        video["Position"]["Left"] = 0;
        video["Position"]["Top"] = 0;
        video["Position"]["Width"] = 1920;
        video["Position"]["Height"] = 1080;    
        videoMixer["Detail"].append(video); 
       
        Json::Value video1 = Json::Value::null;
        video1["Picture"] = 0;
        video1["Layer"] = 1;
        video1["Stream"]["Channel"] = 1;
        video1["Stream"]["Type"] = "OSD";

        string content;
        bool result = getDisplayinfo(table, content);
        if(!result)
        {
            return false;
        }
        
        video1["Stream"]["Content"] = content;
        
        video1["Position"]["Left"] = 200;
        video1["Position"]["Top"] = 200;
        video1["Position"]["Width"] = 48;
        video1["Position"]["Height"] = 48;
        videoMixer["Detail"].append(video1);

        stream["VideoMixer"] = videoMixer;    
        root["StreamSource"].append(stream);

        setCurtainLayout(root);

        Json::Value root2 = Json::Value::null;
        root2["Number"] = CustomNum;
        root2["PlayMode"] = 0;
        root2["Action"] = 1;
        setPlayStrategy(root2);

        playNum = CustomNum;
    }
    else if(playNum == StreamerNum) 
    {
        StreamerCurtainPlay::instance()->playStreamerCurtain(LOCAL_STREAMER);
        return true;
    }
    else if(playNum < CustomNum) 
    {        
        Json::Value curtainTable = Json::Value::null;
        curtainTable["Number"] = playNum;
        curtainTable["Action"] = true;       
        setCurtainLayout(curtainTable, false);//读取和解析配置   
    }

    ///play        
	Json::Value root2 = Json::Value::null;
    root2["Number"] = playNum;
    root2["PlayMode"] = 0;
    root2["Action"] = 1;
    setPlayStrategy(root2);
    


  #else
  {
  
    sleep(5);

    m_detectThread.start([this](Fdt::Thread *thread){this->detectThreadProc(thread);}); //启动单独线程检测新camera
  }
  #endif

#endif

    LOG_PrintInfo("playStartUpCurtain succcess\n");

    return true;
}


bool CurtainActManager::productTestCurtainPlay(){
    Json::Value root2 = Json::Value::null;
    root2["PlayMode"] = 0;
    root2["Action"] = 1;

#ifdef  MODEL_ROOMS
    root2["Number"] = RoomsProductTest;
#elif  MODEL_AIR
    root2["Number"] = AirProductTest;
#else
    return false;
#endif
    return setPlayStrategy(root2);    
}

uint8_t CurtainActManager::getUsbVideoInParam(void)
{
    return m_usbVideoInFlg;
}

bool CurtainActManager::usbVideoRealTimeInfo(std::string &usbPort, bool &isH26x)
{
    uint8_t dealFlg = getUsbVideoInParam();
    if ((dealFlg & 0x01) == 0x01) //byom视频来自usb camera
    {
        //判定视频设备的接口
        std::map<std::string, std::string> posInfo;        
        UsbAVStream::instance()->getUsbPlayPos(posInfo);
        
        usbPort = posInfo["video"];
        if(Media::UsbInStream::instance(usbPort)->isH26xFormat()) //H26X格式
        {
            isH26x = true;    
        }

        return true;
    }

    return false;
}

bool CurtainActManager::isUsbVideoCapture()
{
    uint8_t dealFlg = getUsbVideoInParam();
    LOG_PrintInfo("dealFlg = %x, m_playCurtainNum=%d, mediaCtl_g.uvcState=%d\n", dealFlg, m_playCurtainNum, mediaCtl_g.uvcState);
    
    if (((dealFlg & 0x01) == 0x01 && m_playCurtainNum == DymicMirrorNum)
      || (((dealFlg >> 1) & 0x01) == 0x01 && mediaCtl_g.uvcState == 1) 
      || ((dealFlg >> 2) != 0))
    {        
        return true;
    }

    return false;
}

bool CurtainActManager::ctrlUsbVideo(bool actFlg)
{
    if(!actFlg && isUsbVideoCapture()) //关闭时判断其他链路是否在使用
    {
        return true; 
    }

    uint8_t dealFlg = getUsbVideoInParam();
    if (((dealFlg >> 1) & 0x01) == 0x01) //usbtypecout
    {
        ///动态启动视频设备
        std::map<std::string, std::string> posInfo;        
        Media::UsbAVStream::instance()->getUsbPlayPos(posInfo); 
        std::string usbPort = posInfo["video"];
        Media::UsbInStream::instance(usbPort)->dynamicStartVideo(actFlg);
    }

    return true;
}



bool CurtainActManager::isAudioNeedResampler(StreamInfo& inputStream, int inRate)
{
    CurtainInfo curtainInfo = {0};
    StreamCofigInfo configInfo;
    AudioMixerInfo audioMixerInfo = {0};
    StreamInfo stream = {0};
	int totalInput = 0;
	bool ret = false;
	memset(&configInfo, 0, sizeof(StreamCofigInfo));
	
    //获取拼接布局
    curtainInfo = m_playCurtainInfo;

    for(int i = 0; i < curtainInfo.outNum; ++i)
    {
        configInfo = curtainInfo.cofigInfo[i];
        audioMixerInfo = configInfo.audioMixerInfo;
        totalInput = audioMixerInfo.totalInput;
        stream = audioMixerInfo.audioInfo[0].audioStream;
        
        if(stream.type == inputStream.type
          || strcmp(stream.content, inputStream.content) == 0)
        {
            if(totalInput > 1)
            {
                return false; //暂定混音都需重采样
            }
            
            if(audioMixerInfo.sampleRate == inRate)
            {
                ret = true;
            }
        }  
    }

    return ret;
}

bool CurtainActManager::saveCurPlayNum(int num)
{
    if(TailProductTest == num || RoomsProductTest == num || AirProductTest == num || DymicMirrorNum == num){
        return true;
    }
    int ret;
    char key[8] = {0};

    sprintf(key, "%d", num);
    ret = INI_KeySet(CONFIG_PATH, "Curtain", "playNum", key);
    if (ret)
    {
        return false;
    }

    return true;
}

bool CurtainActManager::getCurPlayNum(int* num)
{
    int ret;
    
    ret = INI_KeyGetInt(CONFIG_PATH, "Curtain", "playNum", num);
    if (ret)
    {
        return false;
    }

    return true;
}

bool CurtainActManager::getSpecificNumCurtain(Json::Value &table, int curtainNum){
	Json::Value curtainTable;
    getJsonTable(configPathCurtain, curtainTable);
	
	if(!curtainTable.isMember("Layouts") || !curtainTable["Layouts"].isArray()){
		LOG_PrintError("faild to read json Layouts\n");
		return false;
	}
	Json::Value layouts = curtainTable["Layouts"];
	
	//读取文件中存储的所有场景，如果存在就赋值
	for(uint i = 0; i < layouts.size(); i++){
		if(!layouts[i].isMember("Number") || !layouts[i]["Number"].isInt()){
			LOG_PrintError("json data format invalid\n");
			return false;
		}
		int number = layouts[i]["Number"].asInt();
		//LOG_PrintInfo("curtain number : %d\n", number);
		if(number == curtainNum)
		{
		    table = layouts[i];
			return true;
		}
	}
	return false;
}

bool CurtainActManager::getDymicCoordinate(Json::Value &table){
	 return  getJsonTable(dymicCoordinatePath, table);
}

bool CurtainActManager::dymicSwitchCurtain(bool state)
{
    int num = m_playCurtainNum;

    LOG_PrintInfo("dymicSwitchCurtain enter,state=%d, CurPlayNum=%d\n", state, num);

    if(num == DymicMirrorNum && state == false)
    {
        if(m_dymicSetNum < StreamerNum)
        {
            ///读取和解析配置
            Json::Value curtainTable = Json::Value::null;
            curtainTable["Number"] = m_dymicSetNum;
            curtainTable["Action"] = true;        
            setCurtainLayout(curtainTable, false); 
        }
        
        ///play 
        if(m_dymicSetNum == StreamerNum)
        {
            StreamerCurtainPlay::instance()->playStreamerCurtain(LOCAL_STREAMER);//数字标牌
        }
        else
        {
        	Json::Value root2 = Json::Value::null;
            root2["Number"] = m_dymicSetNum;
            root2["PlayMode"] = 0;
            root2["Action"] = 1;
            setPlayStrategy(root2);
        }
        return true;
    }
    else if(num != DymicMirrorNum && state == true)
    { 
        m_dymicSetNum = num; 
        
        if(!dymicSwitchTable(true))
        {
            errorf("dymicSwitchTable failed\n");
            return false;
        }

        ///play        
    	Json::Value root2 = Json::Value::null;
        root2["Number"] = DymicMirrorNum;
        root2["PlayMode"] = 0;
        root2["Action"] = 1;
        setPlayStrategy(root2);
    }

    return true;
}


void CurtainActManager::detectThreadProc(Fdt::Thread *thread)
{
    thread->setPriority(Fdt::PRIORITY_NORMAL, Fdt::POLICY_RR);

    getSpecificNumCurtain(m_recentSwitchTable, MultiCameraSwitchNum);

    MediaUdpServer::instance(UDP_PORT_CONSOLE)->serverSocketInit(); //启动udpserver，接收控制台指令

    //读取需要管理的子设备的IP
    Json::Value table = Json::nullValue;    
	IConfigInterface::GetInstance()->Get("SlaveDevice", table);
	if(!table.isMember("CameraIp")
	  || !table["CameraIp"].isArray())
	{
	    errorf("SlaveDevice config error\n");
        return;
	}	
    Json::Value strArray = table["CameraIp"];
    std::string devIp;
	for(int i = 0; i < strArray.size(); i++)
    {
        devIp = strArray[i].asString();
        if(MediaTcpClient::instance(devIp)->creatSocketConnect(TCP_PORT_CAMERA)
          && MediaUdpClient::instance(devIp)->creatSocketConnect(UDP_PORT_VISCA))
        {
            CurtainActManager::instance()->multiCameraAddDel(devIp);
        } 
    }
    
    if(strArray.size() > 0)
    {   
        m_multiCamreaMutex.lock();
        
        Json::Value root = Json::Value::null;
        root["Number"] = MultiCameraSwitchNum;
        root["PlayMode"] = 0;
        root["Action"] = 1;
        setPlayStrategy(root);


        m_multiCamreaMutex.unlock();
    } 

    return;
}


bool CurtainActManager::multiCameraAddDel(std::string cameraIp)
{
    std::lock_guard<std::mutex> guard(m_multiCamreaMutex);
    LOG_PrintInfo("multiCameraAdd enter,CameraIp = %s\n", cameraIp.c_str());
    
    Json::Value table = m_recentSwitchTable;
    //getSpecificNumCurtain(table, MultiCameraSwitchNum);

    if(!table.isMember("StreamSource"))
    {  
        LOG_PrintError("multiCameraAdd Json params is error\n");
        return false;
    }

    std::string devIp = cameraIp;

    /*if(devIp == "192.168.16.32")
    {
        devIp = "192.168.16.30";
    }
    else if(devIp == "192.168.18.45")
    {
        devIp = "192.168.18.245";
    }*/

    Json::Value streamSource = Json::Value::null;        
    streamSource = table["StreamSource"];            
    int outNum = streamSource.size();

    for(int i = 0; i < outNum; ++i)
    {
        ///输出接口类型
        if((!streamSource.isArray()) 
            || (!streamSource[i].isMember("OutputType"))
            || streamSource[i]["OutputType"].asString() != "USBTYPECOUT")
        {
            continue;
        }

        Json::Value singleStream = streamSource[i];

        if((!singleStream.isMember("VideoMixer"))
           || (!singleStream["VideoMixer"].isMember("Detail")))
        {
            LOG_PrintError("multiCameraAdd Json params is error\n");
            return false;
        }

        std::string url = "rtsp://" + devIp + "/live/mainstream";
        bool actFlg = true;
 
        uint inputNum = singleStream["VideoMixer"]["Detail"].size();
        for(int j = 0; j < inputNum; ++j)
        {
            Json::Value video = singleStream["VideoMixer"]["Detail"][j];  
            if((!video.isMember("Stream"))
              || (!video["Stream"].isMember("Content")))
            {
                continue;
            }

            if(url == video["Stream"]["Content"].asString())
            {
                //singleStream["VideoMixer"]["Detail"].removeIndex(j, &video);
                actFlg = false;
                break;
            }
        }
        
        if(actFlg)  
        {
            unsigned int videoChn = singleStream["VideoMixer"]["Detail"].size();
            m_ipToChannelMap[devIp] = videoChn;                        

            Json::Value video = Json::Value::null;        
            video["Picture"] = 0;
            video["Layer"] = 1;
            video["Stream"]["Channel"] = videoChn;
            video["Stream"]["Type"] = "RTSP";
            video["Stream"]["Content"] = url;
            video["Position"]["Left"] = 0;
            video["Position"]["Top"] = 0;
            if(videoChn == 0)
            {
                video["Position"]["Width"] = 1920;
                video["Position"]["Height"] = 1080;   
            }
            else
            {
                video["Position"]["Width"] = 0;
                video["Position"]["Height"] = 0;   
            }
            singleStream["VideoMixer"]["Detail"].append(video);
        }

        streamSource[i] = singleStream;

        table["StreamSource"] = streamSource;

        //parse
        parseCurtainLayout(table); //不写入

        m_recentSwitchTable = table;

        printf("multiCameraAddDel m_recentSwitchTable = %s\n", m_recentSwitchTable.toStyledString().c_str());

        break;
    }

    return true;
}


bool CurtainActManager::multiCameraSwitch(std::string cameraIp)
{
    std::lock_guard<std::mutex> guard(m_multiCamreaMutex);
    LOG_PrintInfo("dymicSwitchCurtain enter,curCameraIp = %s, lastCameraIp=%s\n", cameraIp.c_str(), m_lastSwitchCameraIp.c_str());

    if(m_lastSwitchCameraIp == cameraIp)
    {
        LOG_PrintWarn("Not Need to switch camera\n");
        return false;
    }
    
    std::string devIp = cameraIp;

    /*if(devIp == "192.168.16.32")
    {
        devIp = "192.168.16.30";
    }
    else if(devIp == "192.168.18.45")
    {
        devIp = "192.168.18.245";
    }*/
    
    Json::Value table = m_recentSwitchTable;
    //getSpecificNumCurtain(table, MultiCameraSwitchNum);

    if(!table.isMember("StreamSource") )
    {  
        LOG_PrintError("multiCameraSwitch Json params is error\n");
        return false;
    }

    Json::Value streamSource = Json::Value::null;        
    streamSource = table["StreamSource"];            
    int outNum = streamSource.size();

    for(int i = 0; i < outNum; ++i)
    {
        ///输出接口类型
        if((!streamSource.isArray()) 
            || (!streamSource[i].isMember("OutputType"))
            || streamSource[i]["OutputType"].asString() != "USBTYPECOUT")
        {
            //errorf("multiCameraSwitch Json params is error\n");
            continue;
        }

        Json::Value singleStream = streamSource[i];

        if((!singleStream.isMember("VideoMixer"))
           || (!singleStream["VideoMixer"].isMember("Detail"))
           || (!singleStream["VideoMixer"]["Detail"][0].isMember("Stream")))
        {
            LOG_PrintError("multiCameraSwitch Json params is error\n");
            return false;
        }

        for(uint j = 0; j < singleStream["VideoMixer"]["Detail"].size(); ++j)
        {
            Json::Value positionInfo = singleStream["VideoMixer"]["Detail"][j]["Position"];
            Json::Value streamInfo = singleStream["VideoMixer"]["Detail"][j]["Stream"];
        
            if((!streamInfo.isMember("Type"))
               || (!streamInfo.isMember("Channel"))
               || (streamInfo["Type"].asString() != "RTSP")
               || (!positionInfo.isMember("Width"))
               || (!positionInfo.isMember("Height")))
            {
                LOG_PrintError("multiCameraSwitch Json params is error\n");
                return false;
            }

            if(m_ipToChannelMap[devIp] == streamInfo["Channel"].asInt())
            {
                positionInfo["Width"] = 1920;
                positionInfo["Height"] = 1080;
            }
            else
            {
                positionInfo["Width"] = 0;
                positionInfo["Height"] = 0;
            }

            singleStream["VideoMixer"]["Detail"][j]["Position"] = positionInfo;

        }
        
        
        streamSource[i] = singleStream;

        table["StreamSource"] = streamSource;

        //parse
        parseCurtainLayout(table); //不写入

        m_recentSwitchTable = table;

        m_playCurtainInfo = m_curtainInfoMap[MultiCameraSwitchNum]; //重新设置当前幕墙

        m_lastSwitchCameraIp = cameraIp;

        printf("multiCameraSwitch m_recentSwitchTable = %s\n", m_recentSwitchTable.toStyledString().c_str());

        break;

    }

    return true;
}

bool CurtainActManager::usbStreamCheck(Json::Value& table)
{
    std::map<std::string, std::string> posInfo;
    bool isUpdate = false;
    UsbAVStream::instance()->getUsbStreamPos(posInfo, isUpdate);
    
    if(!table.isMember("StreamSource")
      || (table["StreamSource"].size() <= 0))
    {
        errorf("Json params is error\n");
        return false;
    }

    Json::Value streamValue = Json::Value::null;
    Json::Value sourseValue = Json::Value::null;
    Json::Value detail = Json::Value::null;
    std::string usbType;
    uint mixNum = 0;
    uint outNum = table["StreamSource"].size();

    for(uint i = 0; i < outNum; ++i)
    {
        sourseValue = table["StreamSource"][i];
        if((!sourseValue.isMember("VideoMixer") && !sourseValue.isMember("AudioMixer"))
          || !sourseValue.isMember("OutputType"))
        {
            continue;
        }

        if(sourseValue["OutputType"].asString() == "USBTYPEAOUT1"
          || sourseValue["OutputType"].asString() == "USBTYPEAOUT2")
        {
            if(posInfo["audio"] == UsbAVStream::instance()->USB_IN_1)
            {
                sourseValue["OutputType"] = "USBTYPEAOUT1";
            }
            else
            {
                sourseValue["OutputType"] = "USBTYPEAOUT2";
            }
        }

        if(sourseValue.isMember("VideoMixer")
          && sourseValue["VideoMixer"].isMember("Detail"))
        {

            detail = sourseValue["VideoMixer"]["Detail"];
            mixNum = detail.size();

            for(uint j = 0; j < mixNum; ++j)
            {
                if(detail[j].isMember("Stream")
                  && (detail[j]["Stream"].isMember("Type"))
                  && (detail[j]["Stream"]["Type"].asString() == "USBTYPEAIN"))
                {
                    detail[j]["Stream"]["Content"] = posInfo["video"];                       
                }
            }
            
            sourseValue["VideoMixer"]["Detail"] = detail;
        }

        if(sourseValue.isMember("AudioMixer")
          && sourseValue["AudioMixer"].isMember("Detail"))
        {

            detail = sourseValue["AudioMixer"]["Detail"];
            mixNum = detail.size();

            for(uint j = 0; j < mixNum; ++j)
            {
                if(detail[j].isMember("Stream")
                  && (detail[j]["Stream"].isMember("Type"))
                  && (detail[j]["Stream"]["Type"].asString() == "USBTYPEAIN"))
                {
                    detail[j]["Stream"]["Content"] = posInfo["audio"];                       
                }
            }
            
            sourseValue["AudioMixer"]["Detail"] = detail;
        }

        table["StreamSource"][i] = sourseValue;
        
    }
    
    LOG_PrintInfo("CurtainActManager::usbStreamCheck newcurtain=%s\n", table.toStyledString().c_str());

    return true;
}

bool CurtainActManager::isPlayDefCurtain(bool& iFlag, int& playNum)
{
    playNum = m_playCurtainNum;
    iFlag = false;
    if((m_playCurtainNum == RoomsDefaultMeeting)
      || (m_playCurtainNum == AirDefaultMeeting)
      || (m_playCurtainNum == StreamerNum)
      || (m_playCurtainNum == DymicMirrorNum 
          && (m_dymicSetNum == RoomsDefaultMeeting || m_dymicSetNum == AirDefaultMeeting || m_dymicSetNum == StreamerNum)))
    {
        iFlag = true;
    }

    return true;
}


bool CurtainActManager::audioOutSwitch()
{
    std::string uacPos;  
    StreamOutInterface uacOut; 
    if(UsbAVStream::instance()->getUacOutStatus(uacPos))
    {    
        if(uacPos == "usb-1.1")
            uacOut = USBTYPEA_OUT1;
        else if(uacPos == "usb-1.2")
            uacOut = USBTYPEA_OUT2;

        if(m_currentAudioOut != uacOut)
        {   
            m_currentAudioOut = uacOut;
            LOG_PrintInfo("audioOutSwitch::m_currentAudioOut=%d, usbAudio=%s\n", m_currentAudioOut, uacPos.c_str());    
            return true; 
        }
    }
    else if(m_currentAudioOut != HDMI_OUT)
    {
        m_currentAudioOut =  HDMI_OUT;  

        LOG_PrintInfo("audioOutSwitch::m_currentAudioOut=%d\n", m_currentAudioOut);
        return true;    
    }

    LOG_PrintInfo("audioOutSwitch::m_currentAudioOut=%d, audioOutSwitch no need \n", m_currentAudioOut);

    return false;
            
}

bool CurtainActManager::dymicSwitchTable(bool dymicFlg)
{
    Json::Value table = m_playCurtainTable;

    bool aoStatus = audioOutSwitch();

    ///usb信息更新且输出类型不更新
    if(!dymicFlg && !aoStatus)
    {
        usbStreamCheck(table);
         
        return parseCurtainLayout(table);
    }

    ///动态投屏添加处理
    if(m_dymicSetNum < StreamerNum || aoStatus)
    {
        getSpecificNumCurtain(table, m_dymicSetNum);

        if(!dymicFlg || aoStatus)
        {
            usbStreamCheck(table);
        }
    }
    
    if(!table.isMember("DymicSwitchCurtain") 
        || !table["DymicSwitchCurtain"].asBool()
        || !table.isMember("StreamSource") )
    {  
        LOG_PrintError("DymicSwitchCurtain params is error\n");
        return false;
    }

    Json::Value coordianteTable;
    getDymicCoordinate(coordianteTable);
    if((!coordianteTable.isMember("FullScreen"))
        || (!coordianteTable.isMember("PinpScreen"))
        || (!coordianteTable.isMember("MontageScreen")))
    {
        LOG_PrintError("DymicCoordinate params is error\n");
        return false;
    }

    Json::Value streamSource;        
    streamSource = table["StreamSource"];          
    
    int outNum = streamSource.size();
    int dymicMode = 0;
    int videoMode = 0;
    for(int i = 0; i < outNum; ++i)
    {
        ///输出接口类型
        if((!streamSource.isArray()) 
            || (!streamSource[i].isMember("OutputType"))
            || (!streamSource[i].isMember("DymicSwitchMode"))
            || (!streamSource[i].isMember("MirrorDisplayMode")))
        {
            errorf("Json params is error\n");
            continue;
        }

        Json::Value singleStream = streamSource[i];

        dymicMode = singleStream["DymicSwitchMode"].asInt();

        if((dymicMode & 0x01) == 0x01) //视频需要拼接
        {
            videoMode = singleStream["MirrorDisplayMode"].asInt();

            if(!singleStream.isMember("VideoMixer"))
            {
                singleStream["VideoMixer"]["Width"] = 1920;
                singleStream["VideoMixer"]["Height"] = 1080;
                singleStream["VideoMixer"]["Fps"] = 30;
            }

            Json::Value mirrorVideo;
            mirrorVideo["Picture"] = 0;
            mirrorVideo["Layer"] = 0;
            mirrorVideo["Stream"]["Channel"] = 7;//15
            mirrorVideo["Stream"]["Type"] = "MIRROR";
            mirrorVideo["Stream"]["Content"] = "private";
            
            if(videoMode == 1)//0-不加入拼接，1-全屏展示， 2-拼接 3-画中画
            {
                mirrorVideo["Position"] = coordianteTable["FullScreen"][0]["Position"];

                if(singleStream["VideoMixer"].isMember("Detail"))
                {

                    singleStream["VideoMixer"]["Detail"].clear();
                }
                
                singleStream["VideoMixer"]["Detail"].append(mirrorVideo);
            }                
            else if(videoMode == 2)
            {
                mirrorVideo["Position"] = coordianteTable["MontageScreen"][0]["Position"];
                
                if(!singleStream["VideoMixer"].isMember("Detail"))
                {
                    singleStream["VideoMixer"]["Detail"].append(mirrorVideo);
                }
                else
                {
                    Json::Value VideoDetail = singleStream["VideoMixer"]["Detail"];

                    singleStream["VideoMixer"]["Detail"].clear();
                    singleStream["VideoMixer"]["Detail"].append(mirrorVideo);
                    
                    for(uint i = 0; i < VideoDetail.size(); ++i)
                    {
                        uint index = i + 1;
                        if(VideoDetail[i].isMember("Position") && (index < coordianteTable["MontageScreen"].size()))
                        {
                            VideoDetail[i]["Position"] = coordianteTable["MontageScreen"][index]["Position"];
                        }
                        
                        singleStream["VideoMixer"]["Detail"].append(VideoDetail[i]);
                    }
                }
            }
            else if(videoMode == 3)
            {
                mirrorVideo["Position"] = coordianteTable["PinpScreen"][0]["Position"];
                
                if(!singleStream["VideoMixer"].isMember("Detail"))
                {
                    singleStream["VideoMixer"]["Detail"].append(mirrorVideo);
                }
                else
                {
                    Json::Value VideoDetail = singleStream["VideoMixer"]["Detail"];

                    singleStream["VideoMixer"]["Detail"].clear();
                    singleStream["VideoMixer"]["Detail"].append(mirrorVideo);
                    
                    for(uint i = 0; i < VideoDetail.size(); ++i)
                    {
                        uint index = i + 1;
                        if(VideoDetail[i].isMember("Position") && (index < coordianteTable["PinpScreen"].size()))
                        {
                            VideoDetail[i]["Position"] = coordianteTable["PinpScreen"][index]["Position"];
                        }
                        
                        singleStream["VideoMixer"]["Detail"].append(VideoDetail[i]);
                    }
                }
            }
        }

        if(((dymicMode >> 1) & 0x01) == 0x01) //需要音频混音
        {
            std::string outputType = singleStream["OutputType"].asString();
            if((m_currentAudioOut == HDMI_OUT && (outputType == "USBTYPEAOUT1" || outputType == "USBTYPEAOUT2"))
                  || (m_currentAudioOut != HDMI_OUT && outputType == "HDMIOUT"))
            {
                ; //不处理
            }
            else
            {                
                int audioMode = 0;
                if(singleStream.isMember("AudioMixer") 
                  && singleStream["AudioMixer"].isMember("Detail"))
                {
                    audioMode = singleStream["MirrorDisplayMode"].asInt();  

                    Json::Value mirrorAudio;
                    mirrorAudio["Stream"]["Channel"] = 7;
                    mirrorAudio["Stream"]["Type"] = "MIRROR";
                    mirrorAudio["Stream"]["Content"] = "private";

                    if(audioMode == 0 || audioMode == 1) //考虑兼容性，0与1都是混音
                    {
                        singleStream["AudioMixer"]["Detail"].append(mirrorAudio);
                    }
                    else if(audioMode == 2) //替换
                    {
                        singleStream["AudioMixer"]["Detail"].clear();   
                        singleStream["AudioMixer"]["Detail"].append(mirrorAudio);
                    }
                }
            }
        }

        streamSource[i] = singleStream;
        
    }

    table["StreamSource"] = streamSource;
    table["Number"] = DymicMirrorNum;
    table["CurtainName"] = "DymicMirrorCurtain";
    table["Action"] = true;
    table["DymicSwitchCurtain"] = true;


    LOG_PrintInfo("DymicSwitchTable table=%s\n", table.toStyledString().c_str());
    
    //parse
    return parseCurtainLayout(table);

}

bool CurtainActManager::uacoutChangeDeal(int playNum)
{
    LOG_PrintInfo("---------------uacoutChangeDeal enter\n");
    Json::Value table = m_playCurtainTable;

    parseCurtainLayout(table);
    
    m_playCurtainInfo = m_curtainInfoMap[playNum]; //重新设置当前幕墙信息,同步到audio
    
    return true;
}

bool CurtainActManager::cameraInfoUpdate(bool actVal, std::string devIp)
{
    std::lock_guard<std::mutex> guard(m_cameraInfoMutex);

    if(actVal)
    {
        m_cameraInfoSet.insert(devIp);

        LOG_PrintWarn("Del add ip =%s\n", devIp.c_str()); 
    }
    else
    {

        m_cameraInfoSet.erase(devIp);

        LOG_PrintWarn("Del dev ip =%s\n", devIp.c_str()); 
    }

    return true;   
}

bool CurtainActManager::getCameraInfo(std::set<std::string>& devIpSet)
{
    std::lock_guard<std::mutex> guard(m_cameraInfoMutex);
    devIpSet = m_cameraInfoSet;
    return true;
}



}

